/**
* Copyright (c) By zengqh.
*
* This program is just for fun or demo, in the hope that it  
* will be useful, you can redistribute it and/or modify freely.
*
* Time: 2013/05/21
* File: Camera.cpp
* Blog: http://www.cnblogs.com/zengqh/
**/

#include "Camera.h"

namespace HY
{
Camera::Camera()
{
	dirty_flags_.set_flag(DT_VIEW_MATRIX);
	dirty_flags_.set_flag(DT_PROJ_MATRIX);
	dirty_flags_.set_flag(DT_FRUSTUM);
}

Camera::~Camera()
{

}

void Camera::setNearPlane(float near_clip)
{
	near_clip_ = Max(near_clip, 0.01f);

	dirty_flags_.set_flag(DT_PROJ_MATRIX);
	dirty_flags_.set_flag(DT_FRUSTUM);
}

void Camera::setFarPlane(float far_clip)
{
	far_clip = Max(far_clip, 0.01f);

	dirty_flags_.set_flag(DT_PROJ_MATRIX);
	dirty_flags_.set_flag(DT_FRUSTUM);
}

void Camera::setFov(float fov)
{
	fov = fov;

	dirty_flags_.set_flag(DT_PROJ_MATRIX);
	dirty_flags_.set_flag(DT_FRUSTUM);
}

void Camera::setOrthoSize(float othro)
{
	ortho_size_ = othro;
	aspect_ratio_ = 1.0f;

	dirty_flags_.set_flag(DT_PROJ_MATRIX);
	dirty_flags_.set_flag(DT_FRUSTUM);
}

void Camera::setOrthoSize(const Vector2& size)
{
	ortho_size_ = size.y_;
	aspect_ratio_ = size.x_ / size.y_;

	dirty_flags_.set_flag(DT_PROJ_MATRIX);
	dirty_flags_.set_flag(DT_FRUSTUM);
}

void Camera::setAspectRatio(float ratio)
{
	aspect_ratio_ = ratio;

	dirty_flags_.set_flag(DT_PROJ_MATRIX);
	dirty_flags_.set_flag(DT_FRUSTUM);
}

float Camera::getNearClip() const
{
	if (isPerspective())
	{
		return near_clip_;
	}
	else
	{
		return 0.0f;
	}
}

float Camera::getFarClip() const
{
	if (isPerspective())
	{
		return far_clip_;
	}
	else
	{
		return 0.0f;
	}
}

float Camera::getFov() const
{
	return fov_;
}

float Camera::getOrthoSize() const
{
	return ortho_size_;
}

float Camera::getAspectRatio() const
{
	return aspect_ratio_;
}

const Frustum& Camera::getFrustum() const
{
	if (dirty_flags_.test_flag(DT_FRUSTUM))
	{
		if (isPerspective())
		{
			frustum_.Define(fov_, aspect_ratio_, 1.0f, getNearClip(), far_clip_, world_matrix_)
		}	
		else
		{
			frustum_.DefineOrtho(ortho_size_, aspect_ratio_, 1.0f, getNearClip(), far_clip_, world_matrix_);
		}

		dirty_flags_.reset_flag(DT_FRUSTUM);
	}
}

const Matrix4& Camera::getProjMatrix() const
{
	if (dirty_flags_.test_flag(DT_PROJ_MATRIX))
	{
		proj_matrix_ = getProjMatrix()
	}
}

const Camera::Matrix4& getViewMatrix() const
{

}

Frustum Camera::getSplitFrust(float near_clip, float far_clip)
{

}

Frustum Camera::getViewspaceFrustum() const
{

}

Frustum Camera::getViewSpaceSplitFrustum(float near_clip, float far_clip) const
{

}

Vector2 Camera::worldToScreenPoint(const Vector3& worldPos)
{

}

Vector3 Camera::screenToWorldPoint(const Vector3& screenPos)
{

}

Vector3 Camera::getForwardVector()
{

}

Vector3 Camera::getRightVector()
{

}

Vector3 Camera::getUpVector()
{

}

float Camera::getDistance(const Vector3& worldPos) const
{

}

float Camera::getDistanceSquared(const Vector3& worldPos) const
{

}

void setTransform(const Vector3& eye, const Vector3& target, const Vector3& up)
{

}

void setTransform(const Matrix4& matWorld)
{

}

void Camera::setProjType(uint32 type)
{

}

uint32 Camera::getProjType() const
{

}

bool Camera::isPerspective() const
{

}

bool Camera::isOrthographic() const
{

}

void Camera::makePerspectiveProj()
{
	float nearClip = getNearClip();
	float h = (1.0f / tanf(fov_ * HY_DEGTORAD * 0.5f));
	float w = h / aspect_ratio_;
	float q, r;

	q = (far_clip_ + nearClip) / (far_clip_ - nearClip);
	r = -2.0f * far_clip_ * nearClip / (far_clip_ - nearClip);

	proj_matrix_.m00_ = w;
	proj_matrix_.m02_ = projectionOffset_.x_ * 2.0f;
	proj_matrix_.m11_ = h;
	proj_matrix_.m12_ = projectionOffset_.y_ * 2.0f;
	proj_matrix_.m22_ = q;
	proj_matrix_.m23_ = r;
	proj_matrix_.m32_ = 1.0f;
}

void Camera::makeOrthoProj()
{
	
}

}